package com.tengju.bff.infrastructure.config;

import com.idanchuang.support.mybatis.crypt.CryptInterceptor;
import com.idanchuang.support.mybatis.crypt.config.CryptConfigBean;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;

@Configuration
@MapperScan(basePackages = ClickHouseDBConfig.PACKAGE,
        sqlSessionFactoryRef = "clickhouseSqlSessionFactory",
        sqlSessionTemplateRef = "clickhouseSqlSessionTemplate"
)
public class ClickHouseDBConfig {

    static final String PACKAGE = "com.tengju.data.infrastructure.persistence.mybatis.mapper.clickhouse.*";
    static final String MAPPER_LOCATION = "classpath*:/mapper/**/*.xml";

    @Resource
    private ClickHouseJdbcParamConfig jdbcParamConfig;

    @Bean
    public HikariDataSource clickhouseDataSource() {

        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(jdbcParamConfig.getUrl());
        config.setUsername(jdbcParamConfig.getUsername());
        config.setPassword(jdbcParamConfig.getPassword());
        config.setDriverClassName(jdbcParamConfig.getDriverClassName());
        //是否自定义配置，为true时下面两个参数才生效
        config.addDataSourceProperty("cachePrepStmts", "true");
        //连接池大小默认25，官方推荐250-500
        config.addDataSourceProperty("prepStmtCacheSize", "150");
        //单条语句最大长度默认256，官方推荐2048
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        //新版本MySQL支持服务器端准备，开启能够得到显著性能提升
        config.addDataSourceProperty("useServerPrepStmts", "true");
        config.addDataSourceProperty("useLocalSessionState", "true");
        config.addDataSourceProperty("useLocalTransactionState", "true");
        config.addDataSourceProperty("rewriteBatchedStatements", "true");
        config.addDataSourceProperty("cacheResultSetMetadata", "true");
        config.addDataSourceProperty("cacheServerConfiguration", "true");
        config.addDataSourceProperty("elideSetAutoCommits", "true");
        config.addDataSourceProperty("maintainTimeStats", "false");
        return new HikariDataSource(config);
    }

    @Bean
    public CryptInterceptor cryptInterceptor() {
        return new CryptInterceptor();
    }

    @Bean
    @ConfigurationProperties(prefix = "clickhouse.encryptor")
    public CryptConfigBean cryptConfigBean() {
        return new CryptConfigBean();
    }

    @Bean
    public SqlSessionFactory clickhouseSqlSessionFactory(List<Interceptor> interceptors,
                                                         @Qualifier("clickhouseDataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(ClickHouseDBConfig.MAPPER_LOCATION));

        sessionFactory.setPlugins(interceptors.toArray(new Interceptor[]{}));

        return sessionFactory.getObject();
    }

    @Bean
    public SqlSessionTemplate clickhouseSqlSessionTemplate(@Qualifier("clickhouseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
